package tests;
import static org.junit.Assert.*;

import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import model.EmailBuilder;
import model.Folder;
import model.User;
import model.Email;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
/**
 * This class tests the User class
 * 
 * @author buthainahaldosary
 * @since May 2013
 *
 * @version $Revision: 1.0 $
 */
public class TestUserFoldersAndEmails {

	User user;
	HashMap<String, String> properties;
	List<Folder> folders;
	Folder folder1, folder2;
	Email email1, email2, email3, email4;
	
	/**
	 * This method is called before every test case, it creates a new user, sets its properties and adds two folders to its
	 * list of folders.
	 */
	@Before
	public void setUp()
	{
		user=new User("Buthainah");
		properties=new HashMap<String,String>();
		properties.put("Id", "1");
		properties.put("Name","Laura");
		folder1=new Folder("New parent folder",1,0);
		folder1.setId(1);
		folder2=new Folder("New child folder",1,1);
		folder2.setId(2);
		email1 = new EmailBuilder().setBody("test email 1").setFolderId(1).setFrom("Buthainah").setId(1).setRead(true)
				.setSubject("test subject 1").setTimestamp(new Timestamp(new java.util.Date().getTime())).setTo("sknarula").build();
		folder1.getEmails().add(email1);
		email2 = new EmailBuilder().setBody("test email 2").setFolderId(1).setFrom("Buthainah").setId(1).setRead(true)
				.setSubject("test subject 2").setTimestamp(new Timestamp(new java.util.Date().getTime())).setTo("musab").build();
		folder1.getEmails().add(email2);
		
		email3 = new EmailBuilder().setBody("test email 3").setFolderId(1).setFrom("Buthainah").setId(1).setRead(true)
				.setSubject("test subject 3").setTimestamp(new Timestamp(new java.util.Date().getTime())).setTo("annie").build();
		folder2.getEmails().add(email3);
		email4 = new EmailBuilder().setBody("test email 4").setFolderId(1).setFrom("Buthainah").setId(1).setRead(true)
				.setSubject("test subject 4").setTimestamp(new Timestamp(new java.util.Date().getTime())).setTo("chris").build();
		folder2.getEmails().add(email4);		
		
		folders=new ArrayList<Folder>();
		folders.add(folder1);
		folders.add(folder2);
		user.setFolders(folders);
		
	}
	/**
	 * This method is called after every test case to tear down the user object and force garbage collection.
	 */
	
	@After
	public void tearDown()
	{
		user=null;
		System.gc();
	}
	
	/**
	 * This test case tests the getId method by ensuring that the id is equal to the one specified.
	 */

	@Test
	public void testGetId() {
		
		assertEquals(-1,user.getId());
	}

	/**
	 * This test case tests the getName method by ensuring that the name is equal to the one specified.
	 */
	@Test
	public void testGetName() {
		assertEquals("Buthainah",user.getName());
	}

	/**
	 * This test case tests the setName() method by setting a new Name and ensuring that the user Name equals the new Name.
	 */
	@Test
	public void testSetName() {
		user.setName("Sara");
		assertEquals("Sara",user.getName());
	}

	/**
	 * This test case tests the setProperties() method by setting new properties and ensuring that the user id and name equals the new id and name.
	 * 
	 */

	@Test
	public void testSetProperties() {
		user.setProperties(properties);
		assertEquals(1,user.getId());
		assertEquals("Laura",user.getName());
	}

	/**
	 * This test case tests the folderExists method by checking two folder names.
	 */

	@Test
	public void testFolderExists() {
		assertEquals(user.folderExists("some folder"),false);
		assertEquals(user.folderExists("New parent folder"),true);
	}

	/**
	 * This test case tests the getFolderLevel method.
	 */
	@Test
	public void testGetFolderLevel() {
		assertEquals(1,user.getFolderLevel(1));
	}

	/**
	 * This test case tests the getFolder method by specifying the folder id and ensuring the folder name equals to the one specified.
	 */
	@Test
	public void testGetFolder() {
		
		Folder result=user.getFolder(2);
		assertEquals("New child folder",result.getName());
	}
	
	/**
	 * This test case tests the getParentFolder method by specifying the folder id and ensuring the folder name equals to the one specified.
	 */
	@Test
	public void testGetParentFolder() {
		Folder result=user.getParentFolder(2);
		assertEquals("New parent folder",result.getName());
	}
	/**
	 * This test case tests the getChildFolders method by ensuring that the size of the array list of folders equals to the one specified.
	 */
	@Test
	public void testGetChildFolders() {
		ArrayList<Folder> result=(ArrayList<Folder>) user.getChildFolders(1);
		assertEquals(1,result.size());
	}

	/**
	 * This test case tests the getFolders method by ensuring that the size of the list of folders equals to the one specified.
	 */
	@Test
	public void testGetFolders() {
		List<Folder> result=user.getFolders();
		assertEquals(2,result.size());
	}

	/**
	 * This test case tests the searchEmails method by ensuring that search content correctly search in email "To" field 
	 * using whereToSearch as "to".
	 */
	@Test
	public void testSearchEmailsForToField() {
		List<Email> result=user.searchEmails("to", "chris");
		assertEquals(1,result.size());
	}
	
	/**
	 * This test case tests the searchEmails method by ensuring that search content correctly search in email "To" field 
	 * using whereToSearch as "To".
	 */
	@Test
	public void testSearchEmailsForToFieldCap() {
		List<Email> result=user.searchEmails("To", "chris");
		assertEquals(1,result.size());
	}

	/**
	 * This test case tests the searchEmails method by ensuring that search content correctly search in email "From" field
	* using whereToSearch as "from".
	  */
	@Test
	public void testSearchEmailsForFromField() {
		List<Email> result=user.searchEmails("from", "thain");
		assertEquals(4,result.size());
	}
	
	/**
	 * This test case tests the searchEmails method by ensuring that search content correctly search in email "From" field
	 * using whereToSearch as "From".
	 */
	@Test
	public void testSearchEmailsForFromFieldCap() {
		List<Email> result=user.searchEmails("From", "thain");
		assertEquals(4,result.size());
	}
	
	
	/**
	 * This test case tests the searchEmails method by ensuring that search content correctly search in email "Subject" field
	 * using whereToSearch as "subject".
	 */
	@Test
	public void testSearchEmailsForSubjectField() {
		List<Email> result=user.searchEmails("subject", "subject 1");
		assertEquals(1,result.size());
	}
	
	/**
	 * This test case tests the searchEmails method by ensuring that search content correctly search in email "Subject" field
	 * using whereToSearch as "Subject".
	 */
	@Test
	public void testSearchEmailsForSubjectFieldCap() {
		List<Email> result=user.searchEmails("Subject", "subject");
		assertEquals(4,result.size());
	}
	
	/**
	 * This test case tests the searchEmails method by ensuring that search content correctly search in email "Body" field
	 * using whereToSearch as "body".
	 */
	@Test
	public void testSearchEmailsForBodyField() {
		List<Email> result=user.searchEmails("body", "email 1");
		assertEquals(1,result.size());
	}
	
	/**
	 * This test case tests the searchEmails method by ensuring that search content correctly search in email "Body" field
	 * using whereToSearch as "Body".
	 */
	@Test
	public void testSearchEmailsForBodyFieldCap() {
		List<Email> result=user.searchEmails("Body", "hello");
		assertEquals(0,result.size());
	}

	/**
	 * This test will test searchEmail method which takes four parameters - to, from, subject, body - to ensure that it
	 * will find emails which contain the strings passsed as parameter
	 * Passing null for all fields 
	 */
	@Test(expected=NullPointerException.class)
	public void testSearchEmailWithNull() {
		user.searchEmails(null, null, null, null);
	}
	
	/**
	 * This test will test searchEmail method which takes four parameters - to, from, subject, body - to ensure that it
	 * will find emails which contain the strings passsed as parameter
	 * passing null for to field
	 */
	@Test
	public void testSearchEmailWithNullTo() {
		List<Email> result=user.searchEmails("", "buth", "subject", "email");
		assertEquals(4, result.size());
	}
	
	/**
	 * This test will test searchEmail method which takes four parameters - to, from, subject, body - to ensure that it
	 * will find emails which contain the strings passsed as parameter
	 * passing null for from field
	 */
	@Test
	public void testSearchEmailWithNullFrom() {
		List<Email> result=user.searchEmails("chris", "", "subject", "email");
		assertEquals(1, result.size());
	}
	
	/**
	 * This test will test searchEmail method which takes four parameters - to, from, subject, body - to ensure that it
	 * will find emails which contain the strings passsed as parameter
	 * passing null for subject field
	 */
	@Test
	public void testSearchEmailWithNullSubject() {
		List<Email> result=user.searchEmails("chris", "buthainah", "", "email");
		assertEquals(1, result.size());
	}
	
	/**
	 * This test will test searchEmail method which takes four parameters - to, from, subject, body - to ensure that it
	 * will find emails which contain the strings passsed as parameter
	 * passing null for body field
	 */
	@Test
	public void testSearchEmailWithNullBody() {
		List<Email> result=user.searchEmails("chris", "buthainah", "subject 4", "");
		assertEquals(1, result.size());
	}
	
	/**
	 * This test will test searchEmail method which takes four parameters - to, from, subject, body - to ensure that it
	 * will find emails which contain the strings passsed as parameter
	 * no field is passed as null
	 */
	@Test
	public void testSearchEmailWithNullNoNull() {
		List<Email> result=user.searchEmails("a", "buthainah", "subject", "email");
		assertEquals(3, result.size());
	}
	
}
